package com.liuya.common;

import com.liuya.common.exception.ConvertException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Util {
    private static final Log log = LogFactory.getLog(Util.class);
    public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    public static final SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
    // key/value=ClassName:fieldName/Method
    public static final Map javabeanGetMethodMap = new HashMap();
    // key/value=ClassName:fieldName/Method
    public static final Map javabeanSetMethodMap = new HashMap();

    public static boolean isEmpty(Object[] objs) {
        if (objs == null || objs.length == 0)
            return true;
        else
            return false;
    }

    public static boolean equals(Object o1, Object o2) {
        if (o1 == null) {
            return o2 == null;
        } else {
            return o1.equals(o2);
        }
    }

    /**
     * 转移collection中的javabean属性到一个String数组中
     *
     * @param javabeanData
     * @param javabeanClass
     * @param fields
     * @return
     */
    public static String[][] formatJavabeans(Collection javabeanData, String javabeanClass, String[] fields) {
        if (javabeanData == null || javabeanData.size() == 0) {
            return new String[0][fields.length];
        }

        String[][] result = new String[javabeanData.size()][fields.length];
        int i = 0;

        for (Iterator iter = javabeanData.iterator(); iter.hasNext(); ) {
            Object obj = (Object) iter.next();

            for (int j = 0; j < fields.length; j++) {
                Object invoke = getJavabeanAttribute(obj, fields[j]);

                if (invoke != null) {
                    if (invoke instanceof Date) {
                        Date date = (Date) invoke;
                        result[i][j] = shortSdf.format(date);
                    } else {
                        result[i][j] = invoke.toString();
                    }
                }
            }

            i++;
        }

        return result;
    }

    public static Method getJavabeanGetMethod(String javabeanClass, String fieldName) {
        String cacheKey = javabeanClass + "::" + fieldName;
        Method method = (Method) javabeanGetMethodMap.get(cacheKey);

        if (method == null) {
            // 构造方法
            Class c = null;
            try {
                c = Class.forName(javabeanClass);
            } catch (ClassNotFoundException e2) {
                log.error("", e2);
                throw new ConvertException(e2);
            }

            String refinedFieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            String methodName = "get" + refinedFieldName;
            try {
                method = c.getMethod(methodName, null);
            } catch (SecurityException e) {
                log.error("", e);
                throw new ConvertException(e);
            } catch (NoSuchMethodException e) {
                methodName = "is" + refinedFieldName;

                try {
                    method = c.getMethod(methodName, null);
                } catch (SecurityException e1) {
                    log.error("", e1);
                    throw new ConvertException(e);
                } catch (NoSuchMethodException e1) {
                    log.error("", e1);
                    throw new ConvertException("get" + refinedFieldName + " or is" + refinedFieldName + " method not found in class " + javabeanClass);
                }
            }

            // 缓存方法
            javabeanGetMethodMap.put(cacheKey, method);
        }

        return method;
    }

    public static Collection sub(Collection coll, int first, int size) {
        if (coll == null) {
            return null;
        }

        if (coll.size() < size && first == 0) {
            return coll;
        } else {
            List sub = new ArrayList(size);

            int i = -1;
            int fetchsize = 0;
            for (Iterator iter = coll.iterator(); iter.hasNext(); ) {
                Object object = (Object) iter.next();
                i++;
                if (i < first) {
                    continue;
                }

                sub.add(object);
                fetchsize++;

                if (fetchsize == size) {
                    break;
                }
            }

            return sub;
        }
    }

    public static Object get(Collection coll, int index) {
        if (coll instanceof List) {
            return ((List) coll).get(index);
        } else {
            int i = 0;
            for (Iterator iter = coll.iterator(); iter.hasNext(); ) {
                Object object = (Object) iter.next();
                if (i == index) {
                    return object;
                }

                i++;
            }
        }

        return null;
    }

    public static void setJavabeanAttribute(Object o, String field, String fieldClassName, Object fieldValue) {
        int indexOf = field.indexOf(".");

        while (indexOf > 0) {
            String innerField = field.substring(0, indexOf);

            // get field object
            String name = o.getClass().getName();
            Method getMethod = getJavabeanGetMethod(name, innerField);

            Object innerValue = null;
            try {
                innerValue = getMethod.invoke(o, null);
            } catch (Exception e) {
                log.error("", e);
                throw new ConvertException(e);
            }

            if (innerValue == null) {
                // instance it
                try {
                    innerValue = getMethod.getReturnType().newInstance();
                } catch (Exception e) {
                    log.error("", e);
                    throw new ConvertException(e);
                }

                // 设置一个javabean属性
                setJavabeanAttribute(o, innerField, getMethod.getReturnType().getName(), innerValue);
            }

            o = innerValue;
            field = field.substring(indexOf + 1);
            indexOf = field.indexOf(".");
        }

        Method setMethod = getJavabeanSetMethod(o.getClass().getName(), field, fieldClassName);
        try {
            setMethod.invoke(o, new Object[]{fieldValue});
        } catch (Exception e) {
            log.error("", e);
            throw new ConvertException(e);
        }
    }

    private static Method getJavabeanSetMethod(String javabeanClass, String fieldName, String fieldClassName) {
        String cacheKey = javabeanClass + "::" + fieldName;

        Method method = (Method) javabeanSetMethodMap.get(cacheKey);

        if (method == null) {
            // construct method
            Class c = null;
            try {
                c = Class.forName(javabeanClass);
            } catch (ClassNotFoundException e2) {
                log.error("", e2);
                throw new ConvertException(e2);
            }

            String refinedFieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            String methodName = "set" + refinedFieldName;

            Class fieldClass = null;
            if (fieldClassName.equals("int"))
                fieldClass = Integer.TYPE;
            else if (fieldClassName.equals("float"))
                fieldClass = Float.TYPE;
            else if (fieldClassName.equals("long"))
                fieldClass = Long.TYPE;
            else if (fieldClassName.equals("double"))
                fieldClass = Double.TYPE;
            else if (fieldClassName.equals("boolean"))
                fieldClass = Boolean.TYPE;
            else {
                try {
                    fieldClass = Class.forName(fieldClassName);
                } catch (ClassNotFoundException e2) {
                    log.error("", e2);
                    throw new ConvertException(e2);
                }
            }

            try {
                method = c.getMethod(methodName, new Class[]{fieldClass});
            } catch (SecurityException e) {
                log.error("", e);
                throw new ConvertException(e);
            } catch (NoSuchMethodException e) {
                // try isAbc method
                methodName = "is" + refinedFieldName;

                try {
                    method = c.getMethod(methodName, null);
                } catch (SecurityException e1) {
                    log.error("", e1);
                    throw new ConvertException(e);
                } catch (NoSuchMethodException e1) {
                    log.error("", e1);
                    throw new ConvertException("set" + refinedFieldName + " or is" + refinedFieldName + " method not found in class " + javabeanClass);
                }
            }

            // cache method
            javabeanSetMethodMap.put(cacheKey, method);
        }

        return method;
    }

    public static Object getJavabeanAttribute(Object o, String field) {
        int indexOf = field.indexOf(".");

        while (indexOf > 0) {
            String innerField = field.substring(0, indexOf);

            // get field object
            String name = o.getClass().getName();
            Method getMethod = getJavabeanGetMethod(name, innerField);

            try {
                o = getMethod.invoke(o, null);
            } catch (Exception e) {
                log.error("", e);
                throw new ConvertException(e);
            }

            field = field.substring(indexOf + 1);
            indexOf = field.indexOf(".");
        }

        Method getMethod = getJavabeanGetMethod(o.getClass().getName(), field);
        try {
            return getMethod.invoke(o, null);
        } catch (Exception e) {
            log.error("", e);
            throw new ConvertException(e);
        }
    }

    /**
     * 合并给定的字节数组
     * @param arrs
     * @return
     */
    public static byte[] mergeArray(byte[]... arrs) {
        int index = 0;
        int sum = 0;
        for (int i = 0; i < arrs.length; i++) {
            sum = sum + arrs[i].length;
        }
        byte[] result = new byte[sum];
        for (int i = 0; i < arrs.length; i++) {
            int lengthOne = arrs[i].length;
            if (lengthOne == 0) {
                continue;
            }
            System.arraycopy(arrs[i], 0, result, index, lengthOne);
            index = index + lengthOne;
        }
        return result;
    }

    /**
     * 使用正则表达式区别内容，如果合法将返回结果
     * @param pattern
     * @param value
     * @return
     */
    public static boolean pattern(String pattern, String value) {
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(value);
        return m.find();
    }

}
